package com.sddfp.trade.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.sddfp.client.access.TradeLogApi;
import com.sddfp.client.system.UserApi;
import com.sddfp.common.exception.Assert;
import com.sddfp.common.exception.BusinessException;
import com.sddfp.common.pojo.*;
import com.sddfp.common.result.Result;
import com.sddfp.common.result.enums.BorrowStatusEnums;
import com.sddfp.common.result.enums.impl.ResultCode;
import com.sddfp.common.utils.TokenUtils;
import com.sddfp.trade.entity.BorrowRecord;
import com.sddfp.trade.mapper.BorrowRecordMapper;
import com.sddfp.trade.service.IBorrowRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @author yellow Docter
 * @date 2023 -07-31
 * @desc    Primary可以理解为默认优先选择, 同时不可以同时设置多个,
 *          内部实质是设置BeanDefinition的primary属性
 */
@Slf4j
@Service
public class IBorrowRecordServiceImpl extends ServiceImpl<BorrowRecordMapper, BorrowRecord> implements IBorrowRecordService {

    // 注入feign客户端接口代理对象
    @Autowired
    private UserApi userApi;

    @Autowired
    TradeLogApi tradeLogApi;

    @Override
    public void addBorrowRecord(BorrowRecordDTO borrowRecordDTO) {
        // 从token中获取登录用户信息
        Long userId = TokenUtils.getTokenUserId();

        // 创建对象
        BorrowRecord borrowRecord = new BorrowRecord();
        // 设置用户id
        borrowRecord.setUserId(userId);
        // 设置借款期限、借款金额
        borrowRecord.setPeriod(borrowRecordDTO.getPeriod());
        borrowRecord.setAmount(borrowRecordDTO.getAmount());
        // 设置借款编号，        "BO_"
        borrowRecord.setBorrowRecordNo("BO_" + UUID.randomUUID().toString().substring(0,10));
        //borrowRecord.setBorrowRecordNo(
        //UniqueIDGenerator.generator(UserConstant.BORROW_CODE_PREFIX));

        // 远程调用系统管理微服务：根据用户id查询获取用户编码、用户名、身份证号码
        Result<UserInfoVo> userResult = userApi.findById(borrowRecord.getUserId());
        // 断言判断
        Assert.error(
                userResult == null || userResult.getCode() != ResultCode.SUCCESS.getCode(),
                ResultCode.DATA_IS_WRONG);
        // 获取返回结果
        UserInfoVo userInfoVo = userResult.getData();
        // 设置用户编码、借款名称 (如：许敏女士第1次借款)
        borrowRecord.setUserCode(userInfoVo.getUserCode());
        borrowRecord.setName(covertName(userInfoVo));

        // 各种利率 （先写死，应该放到配置文件中）
        borrowRecord.setInvestRate(new BigDecimal("10"));
        borrowRecord.setBorrowerRate(new BigDecimal("10"));
        borrowRecord.setCommissionRate(new BigDecimal("10"));
        // 还款方式：等额本金（DEBJ）、等额本息（DEBX）
        // "DEBX", "等额本息" /"DEBJ", "等额本金"  /"ALL", 一次性还款（含本息）  / "XXHB", "先息后本"
        borrowRecord.setRepaymentWay("DEBX");
        //borrowRecord.setRepaymentWay(PayTypeEnums.DEBX.getCode());
        // 借款状态：新建
        borrowRecord.setBorrowStatus("NEW");
        //borrowRecord.setBorrowStatus(BorrowStatusEnums.NEW.getCode());
        borrowRecord.setCreateDate(new Date());
        borrowRecord.setModifyDate(new Date());
        borrowRecord.setStatus(false);
        borrowRecord.setDescription("无");

        this.save(borrowRecord);
        log.info("保存借款记录成功：{}",borrowRecord);
    }

    /**
     * 处理借款名称 (如：许敏女士第1次借款)
     * @param userInfoVo
     * @return
     */
    private String covertName(UserInfoVo userInfoVo) {
        // 根据用户编码（唯一）查询用户借款次数
        long count = this.count(
                Wrappers.lambdaQuery(BorrowRecord.class)
                        .eq(BorrowRecord::getUserCode, userInfoVo.getUserCode()));
        StringBuffer sb = new StringBuffer();
        sb.append(userInfoVo.getUserName());
        sb.append(getGender(userInfoVo.getIdentityCode()));
        sb.append("第" + (count + 1) );
        sb.append("次借款");
        return sb.toString();
    }

    /**
     * 根据身份证号码返回性别：先生、女士
     */
    private String getGender(String identityCode) {
        // 判断身份证号码必须是18位
        Assert.error(
                identityCode==null || identityCode.length()!=18,
                ResultCode.DATA_IS_WRONG);
        // 截取
        Integer n = Integer.parseInt(identityCode.substring(16,17));
        return n % 2 == 0 ? "女士" : "先生";
    }

    @Override
    public String verifyStatus(Integer approveStatus, Long borrowRecordId) {
        //1、生成流水号并更新借款记录表： borrow_record --> REQ_CODE
        //注意：如果borrow_record表的REQ_CODE流水号已经生成过，就不需要重新重新
        //根据借款记录id查询
        BorrowRecord borrowRecord = this.getById(borrowRecordId);

        if (StringUtils.isEmpty(borrowRecord.getReqCode())) {
            // 生成流水号
            String reqCode = "REQ_" + UUID.randomUUID().toString().substring(0,10);
            // 更新借款记录表流水号字段
            this.update(Wrappers.lambdaUpdate(BorrowRecord.class)
                    .set(BorrowRecord::getReqCode,reqCode)
                    .eq(BorrowRecord::getId,borrowRecordId)
            );
            // 设置流水号到borrowRecord对象中，后面远程调用需要这个参数
            borrowRecord.setReqCode(reqCode);
        }

        //2、调用托管代理服务同步借款信息，远程调用
        //2.1、根据接口规范，准备远程调用参数
        //对象拷贝：borrowRecord --> BorrowSyncRecordVo
        BorrowSyncRecordVo borrowSyncRecordVo = BeanUtil.copyProperties(borrowRecord, BorrowSyncRecordVo.class);
        //2.2、远程调用托管代理，同步借款数据
        //fixme 先模拟一下，写完托管代理接口后再更改
        Result<BaseResult> result = tradeLogApi.syncBorrowRecord(borrowSyncRecordVo);

        //3、根据远程调用结果，返回msg=成功，修改BorrowRecord表的status=1、borrow_status为SYNC
        if (result.getCode() == ResultCode.SUCCESS.getCode()) {
            // 修改状态
            this.update(Wrappers.lambdaUpdate(BorrowRecord.class)
                    .set(BorrowRecord::getStatus,approveStatus)
                    .set(BorrowRecord::getBorrowStatus, BorrowStatusEnums.SYNC.getCode())
                    .eq(BorrowRecord::getId,borrowRecordId)
            );
            return "success";
        }
        throw new BusinessException(ResultCode.FAILED);
    }

    @Override
    public Pages<BorrowRecordVo> queryBorrowRecord(Integer pageNum, Integer pageSize, BorrowRecordQuery borrowRecordQuery) {
        //1. 创建分页对象
        IPage<BorrowRecord> pageParams = new Page<>(pageNum,pageSize);
        //2. 创建条件对象
        LambdaQueryWrapper<BorrowRecord> queryWrapper = Wrappers.lambdaQuery(BorrowRecord.class);
        // 借款期限 -- 区间
        if (borrowRecordQuery.getStartPeriod() != null) {
            queryWrapper.ge(BorrowRecord::getPeriod, borrowRecordQuery.getStartPeriod());
        }
        if (borrowRecordQuery.getEndPeriod() != null) {
            queryWrapper.le(BorrowRecord::getPeriod, borrowRecordQuery.getEndPeriod());
        }
        // 借款状态
        if (StringUtils.isNotBlank(borrowRecordQuery.getBorrowStatus())) {
            queryWrapper.eq(BorrowRecord::getBorrowStatus, borrowRecordQuery.getBorrowStatus());
        }
        // 名称
        if (StringUtils.isNotBlank(borrowRecordQuery.getName())) {
            queryWrapper.like(BorrowRecord::getName, borrowRecordQuery.getName());
        }

        //3. 分页条件查询
        IPage<BorrowRecord> pageData = this.page(pageParams, queryWrapper);
        //3.1 获取当前页数据
        List<BorrowRecord> borrowRecordList = pageData.getRecords();
        //3.2 目标是把：List<BorrowRecord>  --->  List<BorrowRecordVo>
        // 通过hutool的工具类copyToList()方法：参数1：数据源集合； 参数2：要转换的对象类型
        List<BorrowRecordVo> voList = BeanUtil.copyToList(borrowRecordList, BorrowRecordVo.class);

        //4. 返回结果
        Pages<BorrowRecordVo> pages = new Pages<>();
        pages.setList(voList);
        pages.setPageNum(pageNum);
        pages.setPageSize(pageSize);
        pages.setTotal(pageData.getTotal());
        return pages;
    }
}
